import { ArcRotateCamera, Color3, Color4, CubeTexture, Engine, HemisphericLight, Mesh, MeshBuilder, PhotoDome, PointerEventTypes, Scene, StandardMaterial, Texture, Vector3 } from "@babylonjs/core";

//天空盒
export default class SkyBox {

    public engine: Engine;
    public scene: Scene;
    public canvas: HTMLCanvasElement;

    private updateAction: Map<number, (time: number) => {}> = new Map();
    private updateActionId: number = 0;

    public static skyBox: SkyBox;

    public constructor(canvas: HTMLCanvasElement) {
        this.canvas = canvas;
        this.engine = new Engine(canvas, true);
        this.scene = this.createScene();

        this.init();

        SkyBox.skyBox = this;
    }

    private init() {
        this.update(0);
    }

    private createScene() {
        const { engine, canvas } = this;
        let scene = new Scene(engine);
        scene.clearColor = new Color4(0, 0, 0, 1);

        const camera = new ArcRotateCamera('Camera', Math.PI / 2, Math.PI / 3, 10, new Vector3(0, 0, 0), scene);
        camera.attachControl(canvas, true);
        camera.inputs.attached.mousewheel.detachControl();//取消滚动

        const dome = new PhotoDome('demo', 'https://playground.babylonjs.com/textures/360photo.jpg', {
            resolution: 32,
            size: 1000,
            useDirectMapping: false
        }, scene);
        // dome.imageMode = PhotoDome.MODE_SIDEBYSIDE;//or useDirectMapping: false, 用来修改图片视角缩放

        let zoom = 1;
        //捕获全部鼠标事件
        scene.onPointerObservable.add((e) => {
            if (dome == undefined) return;
            console.log(e)
            zoom *= 0.95;//没法区分上下滚动
            dome.fovMultiplier = zoom;
        }, PointerEventTypes.POINTERWHEEL);//过滤除了鼠标滚轮的事件

        const vrHelper = scene.createDefaultVRExperience();

        return scene;
    }

    private update(time: number) {
        const { updateAction, scene } = this;
        updateAction.forEach((action, key) => {
            action(time);
        });
        scene.render();
        requestAnimationFrame((time) => {
            this.update(time);
        });
    }

    public setUpdateAction(action: (time: number) => {}, id: number = -1) {
        const { updateAction } = this;
        let curId = id;
        if (id == -1) {
            curId = this.updateActionId++;
        } else if (id >= this.updateActionId) {
            curId = this.updateActionId++;
        }
        updateAction.set(curId, action);
    }
}